import { WaitForPromiseGeneratorResult } from "../engine/EngineGenerators"
import { TourTransitionType } from "../enum/tourTransition.enum"
import transitionTypeEnum from "../enum/transitionType.enum"
import y from "../math/19674"
import E from "../math/79437"
import OpenDeferred from "../utils/OpenDeferred"
import TourTransitionFactory from "./TourTransitionFactory"
const X = 5
const F = 0.001
const k = (e, t, i, s) => {
  const n = Math.min(e.distanceTo(t), 5),
    r = n * (1 / s) * 1000
  let o = r
  const a = i / r
  if (a > F) {
    o += o * ((a - F) / F)
  }
  const h = Math.abs(e.clone().setX(0).setZ(0).distanceTo(t.clone().setX(0).setZ(0)) / Math.max(n, 1))
  if (h > 0.1) {
    o *= 0.9 + 0.75 * h
  }
  return o
}
export default class TourDirectWalkingTransition {
  settingsData: any
  cameraPose: any
  moveToSweep: any
  updateTransitionSpeed: any
  setRestrictedSweeps: any
  generators: any
  toIndex: number
  currentGenerator: any
  currentTransitionPromise: any
  type: number
  constructor(e, t, i, s, n, r) {
    ;(this.settingsData = e),
      (this.cameraPose = t),
      (this.moveToSweep = i),
      (this.updateTransitionSpeed = s),
      (this.setRestrictedSweeps = n),
      (this.generators = r),
      (this.toIndex = -1),
      (this.currentGenerator = null),
      (this.currentTransitionPromise = null),
      (this.type = TourTransitionType.Move)
  }
  get active() {
    return null !== this.currentTransitionPromise || null !== this.currentGenerator
  }
  get promise() {
    return this.currentTransitionPromise ? this.currentTransitionPromise : Promise.resolve()
  }
  async stop() {
    this.currentTransitionPromise && (await this.onStopRequested(), await this.promise, (this.currentTransitionPromise = null)),
      this.currentGenerator && (this.generators.stopGenerator(this.currentGenerator), (this.currentGenerator = null))
  }
  onStopRequested: any
  start(e) {
    if (this.active) throw Error("Transition already active")
    const { generator: t, deferred: i } = this.build(e.path, e.orientations)
    return this.generators.startGenerator(t), (this.currentGenerator = t), (this.currentTransitionPromise = i.nativePromise()), this
  }
  build(e, t) {
    const i = new OpenDeferred(),
      n = this
    let r = !1
    this.onStopRequested = async () => {
      r = !0
      await this.updateTransitionSpeed(X)
    }
    return {
      generator: function* () {
        let o = 1
        for (; o < e.length && !r; ) {
          const i = o - 1,
            r = e[o],
            a = r.position,
            h = e[i],
            d = t[o],
            c = y.zW(n.cameraPose.rotation, d),
            u = TourTransitionFactory.getTransitionSpeed(n.settingsData),
            p = k(h.position, a, c, u),
            g = {
              transitionType: transitionTypeEnum.Interpolate,
              sweepId: r.id,
              rotation: d,
              transitionTime: p,
              easing: E.vG
            }
          n.setRestrictedSweeps(e, i)
          const m = n.moveToSweep(g)
          yield new WaitForPromiseGeneratorResult(m.nativePromise()), o++
        }
        n.setRestrictedSweeps(null), i.resolve(), (n.currentTransitionPromise = null), n.stop()
      },
      deferred: i
    }
  }
}
